/**
* Copyright 2013 nabla
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
*/
package com.nabla.wapp.report.client.parameter;

import java.util.List;
import java.util.logging.Logger;

import com.nabla.wapp.client.general.LoggerFactory;
import com.nabla.wapp.client.model.field.FieldAttributes;
import com.nabla.wapp.client.model.field.SelectBoxField;
import com.nabla.wapp.client.ui.InvalidatePickListCache;
import com.nabla.wapp.client.ui.form.Form;
import com.nabla.wapp.client.ui.form.SelectBox;
import com.nabla.wapp.report.client.model.ParameterValueMapModel;
import com.nabla.wapp.report.shared.parameter.IParameterValue;
import com.nabla.wapp.report.shared.parameter.IntegerComboBoxParameter;
import com.nabla.wapp.report.shared.parameter.IntegerParameterValue;
import com.nabla.wapp.report.shared.parameter.ParameterValueList;
import com.nabla.wapp.shared.slot.ISlot1;
import com.smartgwt.client.data.DSCallback;
import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.data.DSResponse;
import com.smartgwt.client.data.DataSourceField;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.widgets.form.fields.SelectItem;
import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
import com.smartgwt.client.widgets.form.fields.events.DataArrivedEvent;
import com.smartgwt.client.widgets.form.fields.events.DataArrivedHandler;

public class IntegerComboBoxParameterBinder implements IParameterBinder {

	private static final Logger				log = LoggerFactory.getLog(IntegerComboBoxParameterBinder.class);
	private final IntegerComboBoxParameter		parameter;
	private final ParameterValueList			values;
	private final InvalidatePickListCache		cacheInvalidator = new InvalidatePickListCache();

	public IntegerComboBoxParameterBinder(final IntegerComboBoxParameter parameter, final ParameterValueList values) {
		this.parameter = parameter;
		this.values = values;
	}

	@Override
	public void createModelField(final List<DataSourceField> fields) {
		fields.add(new SelectBoxField(parameter.getName(),
						new ParameterValueMapModel(parameter.getReportId(), parameter.getName(), values),
						IParameterValue.ID, IParameterValue.NAME, FieldAttributes.REQUIRED));
	}

	@Override
	public void createFormItem(final Form form) {
		final SelectBox ctrl = new SelectBox();
		ctrl.setName(parameter.getName());
		ctrl.setText(parameter.getPrompt());
		ctrl.setWidth("100%");
		ctrl.addCriteria(cacheInvalidator);
		form.add(ctrl);
	}

	@Override
	public void storeValue(Form form) {
		final Object value = form.getValue(parameter.getName());
		log.fine("storing value " + parameter.getName() + " = " + value);
		if (value == null)
			values.remove(parameter.getName());
		else
			values.add(new IntegerParameterValue(parameter.getName(), Integer.valueOf(value.toString())));
	}

	@Override
	public void onPreviousChanged(final Form form) {
		final Object currentValue = form.getValue(parameter.getName());
		log.fine(parameter.getName() + ": previous control value changed so invalidate list");
		cacheInvalidator.invalidateCache();
		if (currentValue != null) {
			// refresh list
			final SelectItem ctrl = (SelectItem)form.getItem(parameter.getName());
			ctrl.fetchData(new DSCallback() {
				@Override
				public void execute(DSResponse response, @SuppressWarnings("unused") Object rawData, @SuppressWarnings("unused") DSRequest request) {
					if (response.getStatus() == DSResponse.STATUS_SUCCESS) {
						boolean currentValueStillValid = false;
						final Integer value = Integer.valueOf(currentValue.toString());
						for (Record record : response.getData()) {
							if (record.getAttributeAsInt(ctrl.getValueField()) == value) {
								currentValueStillValid = true;
								break;
							}
						}
						if (currentValueStillValid) {
							log.fine(parameter.getName() + ": current value still valid in updated list");
						} else {
							log.fine(parameter.getName() + ": current value not valid in updated list");
							ctrl.clearValue();
							ChangedEvent.fire(ctrl, null);
						}
					} else {
						ctrl.clearValue();
						ChangedEvent.fire(ctrl, null);
					}
				}
			});
		}
	}

	@Override
	public void bind(final Form form, final ISlot1<String> onReadyHandler) {
		SelectItem ctrl = (SelectItem) form.getItem(parameter.getName());
		ctrl.addDataArrivedHandler(new DataArrivedHandler() {
			@Override
			public void onDataArrived(@SuppressWarnings("unused") DataArrivedEvent event) {
				onReadyHandler.invoke(parameter.getName());
			}
		});
	}

}
